package com.hmdz.rpc;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.AopConfigException;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyFactory implements InvocationHandler,MethodInterceptor {
    private static Logger logger = LoggerFactory.getLogger(ProxyFactory.class);

    private Class targetCass;

    public ProxyFactory(Class targetCass) {
        this.targetCass = targetCass;
    }

    public <T> T getProxyObject() {
        if (targetCass == null) {
            throw new AopConfigException("TargetSource cannot determine target class: " +
                    "Either an interface or a target is required for proxy creation.");
        }
        if ( !targetCass.isInterface() && targetCass.getInterfaces().length <= 0) {
            logger.info("cglib类代理");
            //cglib代理工具类
            Enhancer en = new Enhancer();
            //设置父类
            en.setSuperclass(targetCass);
            //设置回掉函数
            en.setCallback(this);
            return (T)en.create();

        }
        //jdk动态代理
        Class[] classes = targetCass.isInterface() ? new Class[]{targetCass} : targetCass.getInterfaces();
        return (T) Proxy.newProxyInstance(this.getClass().getClassLoader(), classes, this);
    }

    /**
     * jdk动态代理调用类
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
        logger.info("method={}" , method);
        logger.info("进行编码，发送网络请求");
        if ( !targetCass.isInterface()) {
            logger.info("开始调用方法。。。");
            result = method.invoke(targetCass.newInstance(), args);
            logger.info("结束调用方法。。。");
        }
        logger.info("调用完成");
        return result;
    }

    /**
     * cglib动态代理调用类
     * @param o
     * @param method
     * @param objects
     * @param methodProxy
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        logger.info("method{}",method.toString());
        logger.info("begin.....{}", System.currentTimeMillis());
        method.invoke(targetCass.newInstance(), objects);
        logger.info("end.....{}", System.currentTimeMillis());
        return null;
    }
}
